#!/usr/bin/env python
# -*- mode: python; coding: utf-8; -*-
##--------------------------------------------------------------------------##
##
## Copyright (C) 1998-2003 Markus Oberhumer <markus@oberhumer.com>
## Copyright (C) 2003 Mt. Hood Playing Card Co.
## Copyright (C) 2005-2010 Skomoroh <skomoroh@users.sourceforge.net>
## Copyright (C) 2010-2013 Jeremy Austin-Bardo <tjaustinbardo@gmail.com>
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program.  If not, see <http://www.gnu.org/licenses/>.
##
##--------------------------------------------------------------------------##
__docformat__ = 'restructuredtext en'
__all__ = []

from ... import helpstrings as hs
from ... import pilelib as stack
from ...forms import napoleon as nlayout
from ...gamelib import info as gi, game, state
from ...packlib import info as cs
from ...piles import hanafuda as hstack, napoleon as bstack
from ...utillib.misc import kwdefault

Wrap = stack.StackWrapper
GT, SL = gi.GT, gi.SL


class LesserQueue(cs.Hanafuda_Deck, game.Game):
    """
    Finish 2 deck on _foundation_.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        ..pysollib.layouts.napolean.BraidSmallLayout
        - row [4 over 2 cols E, 4 over 2 cols W braid, no offset]
        - reserve [1 N 1 S row E, 1 N 1 S row W braid, no offset]
        - braid [1 N, braid offset]
        - talon [1 E foundation, no offset]
        - waste [1 E talon, no offset]
        - foundation [8 over 2 col E, no offset]

      _talon_ : pysollib.stack.Stack
        .. pysollib.stack.WasteTalon (max_rounds=3)
        Deal 1 card per waste on click. 2 redeal.

      _waste_ : pysollib.stack.Stack
        .. pysollib.stack.WasteStack
        Init 1 card. Build none. Play top.

      _foundation_ : pysollib.stack.Stack
        .. pysollib.stacks.hanafuda.BraidSuit_Foundation
        Init base card per 1. Build in suit by same rank wrap from base card.
        Dir determined by 2nd card on any pile. Play top.

      _row_ : pysollib.stack.Stack
        .. pysollib.stacks.napolean.RowStack
        Init 1 card. Build any from any but reserve or braid. Play top. Max 1
        card.

      _reserve_ : pysollib.stack.Stack
        .. pysollib.stacks.napolean.Reserve
        Init 1 card. Build any. Play top. Gap deal 1 card from braid. Max 1
        card.

      _braid_ : pysollib.stack.Stack
        .. pysollib.stack.OpenStack (max_cards=20)
        Init deal 20 open card. Build none. Play top.

      _hint_ : pysollib.hint.AbstractHint
        .. pysollib.hint.CautiousDefaultHint
    """
    __info__ = dict(id=0x33d92, name='Lesser Queue',
                    category=cs.TYPE_HANAFUDA, game_type=GT.NAPOLEON, decks=2,
                    redeals=2, skill_level=SL.BALANCED, version='0.50fc')
    __author__ = 'Mt. Hood Playing Card'
    __version__ = 7.70

    _layout_ = nlayout.BraidSmallLayout
    _talon_ = Wrap(stack.WasteTalon, max_rounds=3)
    _waste_ = stack.WasteStack
    _foundations_ = (hstack.BraidSuit_Foundation,) * 2
    _rows_ = bstack.RowStack
    _braid_ = Wrap(stack.OpenStack, max_cards=20)
    _reserve_ = bstack.Reserve

    def _create_game(self, **kw):
        """
        _create_game([rows=8, reserves=4, braidcards=20, bases=RANKS]) -> Layout

        Update foundation base rank. Add a canvas info label for base_rank
        next to talon.

        :returns: current layout with piles and their texts set.

        :seealso: `pysollib.layouts.napoleon` for keyword definitions.
        """
        l = self._layout_(self)
        mfxutil.kwdefault(kw, rows=8, reserves=4, braidcards=20, bases=l.RANKS)
        l, s = super(LesserQueue, self)._create_game(**kw), self.s
        lpile = l.s['braid']
        s['braid'].append(self._braid_(lpile.x, lpile.y, game=self,
                                       offset=lpile.offset))
        self.texts['info'] = l.set_info_text(s['talon'], anchor='ss', dx=l.HXS)
        l.defaultAll()
        return l

    def _start(self, **kw):
        """
        Deal initial cards for new game.
          - s[braid] MAX_CARD ea up.
          - s[rows] 1 ea.
          - s[reserves] 1 ea.
          - s[foundations] base. save all caps.

        .. \_start([]) -> None
        """
        for i in range(self.s['braid'][0].cap['max_cards']):
            self.s['talon'].dealRow(rows=self.s['braid'], frames=0)
        self.s['talon'].dealRow(rows=self.s['rows'])
        self.s['talon'].dealRow(rows=self.s['reserves'])
        base_suit = self.s['talon'].TOPCARD['suit']
        self.s['talon'].dealBaseCards(ncards=1, saveinfo=False)
        self._save_stack_caps(self.s['foundations'], base_suit=base_suit)

    @property
    def _highlight_piles(self):
        """
        Get stacks to highlight for possible move.

        :return: empty.
        :rtype: tuple
        """
        return ()

    @state.move_state('fill')
    def _auto_fill(self, stack):
        """
        While braid has cards, fill empty reserve with 1 of its card.
        """
        if not stack.cards:
            if not self.reserve.cards and self.s['braid'][0].cards:
                self.game.move(1, self.game.s['braid'][0], stack)

    @state.not_state('is_preview')
    def _update_text(self):
        """
        Update canvas info label with chosen build direction for foundation.
        """
        if not self.texts['info']:
            return
        cap = self.s['foundations'][0].cap
        base_suit = cap['base_suit']
        text = ('' if base_suit == cs.ANY
                   else '{0} {1}'.format(self.SUIT[base_suit],
                                         hs.BUILD_DIR(cap['dir'])))
        self.texts['info'].config(text=text)


class GreaterQueue(LesserQueue):
    """
    Finish 4 deck on _foundation_.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        ..pysollib.layouts.napolean.BraidSmallLayout
        - row [4 over 2 cols E, 4 over 2 cols W braid, no offset]
        - reserve [2 N 2 S row E, 2 N 2 S row W braid, no offset]
        - braid [1 N, braid offset]
        - talon [1 E foundation, no offset]
        - waste [1 E talon, no offset]
        - foundation [16 over 4 col E, no offset]

      _talon_ : pysollib.stack.Stack
        .. pysollib.stack.WasteTalon (max_rounds=3)
        Deal 1 card per waste on click. 2 redeal.

      _waste_ : pysollib.stack.Stack
        .. pysollib.stack.WasteStack
        Init 1 card. Build none. Play top.

      _foundation_ : pysollib.stack.Stack
        .. pysollib.stacks.hanafuda.BraidSuit_Foundation
        Init base card per 1. Build in suit by same rank wrap from base card.
        Dir determined by 2nd card on any pile. Play top.

      _row_ : pysollib.stack.Stack
        .. pysollib.stacks.napolean.RowStack
        Init 1 card. Build any from any but reserve or braid. Play top. Max 1
        card.

      _reserve_ : pysollib.stack.Stack
        .. pysollib.stacks.napolean.Reserve
        Init 1 card. Play top. Gap deal 1 card from braid. Max 1 card.

      _braid_ : pysollib.stack.Stack
        .. pysollib.stack.OpenStack (max_cards=40)
        Init deal 40 open card. Build none. Play top.

      _hint_ : pysollib.hint.AbstractHint
        .. pysollib.hint.CautiousDefaultHint
    """
    __info__ = dict(id=0x33d93, name='Greater Queue',
                    category=cs.TYPE_HANAFUDA, game_type=GT.NAPOLEON, decks=4,
                    redeals=2, skill_level=SL.BALANCED, version='0.50fc')
    __author__ = 'Mt. Hood Playing Card'
    __version__ = 7.70

    _braid_ = Wrap(stack.OpenStack, max_cards=40)

    def _create_game(self, **kw):
        """
        _create_game([rows=8, reserves=8, braidcards=40, bases=RANKS]) -> Layout

        Update foundation base rank. Add a canvas info label for base_rank
        next to talon.

        :returns: current layout with piles and their texts set.

        :seealso: `pysollib.layouts.napoleon` for keyword definitions.
        """
        mfxutil.kwdefault(kw, reserves=8, braidcards=40)
        return super(GreaterQueue, self)._create_game(**kw)


PROVIDES = [LesserQueue, GreaterQueue]